package com.example.kotlindemo_room

import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase
import java.lang.IllegalStateException

/**
 * exportSchema 是否导出数据库修改记录
 * 需要在build.gradle里面配置记录导出位置
 * 代码如下
 * javaCompileOptions {
 * annotationProcessorOptions {
 * arguments = ["room.schemaLocation": "$projectDir/schemas".toString()]//指定schema导出位置
 * }
 * }
 */
@Database(entities = arrayOf(Student::class), version = 3, exportSchema = true)
abstract class MyDataBase : RoomDatabase() {

    abstract fun getStudentDao(): StudentDao

    companion object {
        private var instance: MyDataBase? = null
        private var DATABASE_NAME = "my_db"

        @Synchronized
        fun getInstance(context: Context): MyDataBase {
            if (instance == null) {
                instance = Room.databaseBuilder(
                    context.applicationContext,
                    MyDataBase::class.java, DATABASE_NAME
                )
//                    .allowMainThreadQueries()//允许Room在主线程操作数据库，不推荐使用
//                    .addMigrations(MIGRATION_1_2)
                    .addMigrations(MIGRATION_1_2, MIGRATION_2_3)
//                    .fallbackToDestructiveMigration()
//                    .createFromAsset("")
                    .build()
            }
            return instance!!
        }


        //数据库升级Migration
        /**
         * 注意：如果用户当前app的数据库版本为1，然后安装了一个数据库版本为3的新安装包
         * Room在升级数据库时，会先判断当前有没有直接从1到3的升级方案MIGRATION_1_3
         * 如果有，就会执行MIGRATION_1_3方法
         * 如果没有
         * 则会先执行MIGRATION_1_2
         * 然后执行MIGRATION_2_3
         * 从而完成数据库的升级
         *
         * 异常处理
         * 如果将数据库升级为4，但是却没有为此写相应的Migration，则会出现一个
         * IllegalStateException异常
         * 加入fallbackToDestructiveMigration方法
         * 该方法会在出现异常时重建数据库
         * 当然，此时数据也会消失。
         * 不推荐在调试时打开，因为出问题时不好体现
         * 还有类似几个方法，指定版本或者降级
         *     .fallbackToDestructiveMigrationFrom()
         *     .fallbackToDestructiveMigrationOnDowngrade()
         *
         * 另外还有.createFromFile()和 .createFromAsset()方法
         * 可以预填充数据
         *
         */
        var MIGRATION_1_2: Migration? = object : Migration(1, 2) {
            override fun migrate(database: SupportSQLiteDatabase) {
                database.execSQL("ALTER TABLE Student ADD COLUMN sex INTEGER NOT NULL DEFAULT 1")
            }
        }

        /**
         * 销毁和重建策略
         * 如果想将Student表中sex字段由Integer改为text类型
         * 最好的是采用销毁重建策略
         * 大致步骤如下
         * 1创建一张符合表结构要求的临时表temp_Student
         * 2将数据从旧表Student复制到临时表temp_Student
         * 3删除旧表Student
         * 4将临时表temp_Student重命名为Student
         * 示例代码如下：
         *
         * */
        var MIGRATION_2_3: Migration? = object : Migration(2, 3) {
            override fun migrate(database: SupportSQLiteDatabase) {
                //1创建一张符合表结构要求的临时表temp_Student,这个sql语句可以在schema日志中复制过来
                database.execSQL("CREATE TABLE temp_Student (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,name TEXT NOT NULL,age INTEGER NOT NULL default 1, sex TEXT NOT NULL)")

                //2将数据从旧表Student复制到临时表temp_Student,id自增长，所以不需要复制
                database.execSQL("insert into temp_Student (age,sex,name) select age,sex,name from Student")

                //3删除旧表Student
                database.execSQL("drop table Student")

                //4将临时表temp_Student重命名为Student
                database.execSQL("alter table temp_Student rename to Student")

            }

        }


    }


}